import { Controller, Get, Param, HttpException, HttpStatus, Res } from '@nestjs/common';
import { ConfigService } from '@nestjs/config';
import { FastifyReply } from 'fastify';
import { join, resolve } from 'path';
import * as fs from 'fs';
import { NotToken } from '@/decorators/not-token.decorator';
import mime from 'mime-types';

@Controller()
export class FileController {
    constructor(private configService: ConfigService) {
    }

    @Get('/static/*')
    @NotToken()
    async getFile(
        @Param('*') fullPath: string,
        @Res() reply: FastifyReply,
    ) {
        try {
            const uploadDir = join(process.cwd(), this.configService.get('FILE_LOCATION'));
            const filePath = resolve(uploadDir, fullPath);

            // 路径安全校验
            if (!filePath.startsWith(uploadDir)) {
                throw new HttpException('路径不合法（禁止路径穿越）', HttpStatus.FORBIDDEN);
            }

            // 检查文件是否存在且可读取
            await new Promise((resolve, reject) => {
                fs.access(filePath, fs.constants.F_OK | fs.constants.R_OK, (err) => {
                    err ? reject(err) : resolve(true);
                });
            });

            // 设置MIME类型
            const mimeType = mime.lookup(filePath) || 'application/octet-stream';
            const charset = mime.charset(mimeType);
            if (charset) {
                reply.header('Content-Type', `${mimeType}; charset=${charset}`);
            } else {
                reply.type(mimeType);
            }

            // 关键修改：使用pipe方法传输流
            const fileStream = fs.createReadStream(filePath);

            // 处理流错误
            fileStream.on('error', (err) => {
                throw new HttpException('文件读取失败', HttpStatus.INTERNAL_SERVER_ERROR);
            });

            // 将文件流管道到响应对象
            fileStream.pipe(reply.raw);

            // 等待流传输完成
            await new Promise<void>((resolve, reject) => {
                fileStream.on('end', () => resolve());  // 现在符合类型要求
                fileStream.on('error', (err) => reject(err));
            });

        } catch (err) {
            throw new HttpException('文件不存在或访问失败', HttpStatus.NOT_FOUND);
        }
    }
}